package com.example.service.impl;


import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.common.utils.CurrentUserUtil;
import com.example.dao.MaskingRuleMapper;
import com.example.dao.SensitiveTypeDao;
import com.example.entity.AlgorithmTypeEnum;
import com.example.entity.domain.MaskingRule;
import com.example.entity.dto.BaseDTO;
import com.example.entity.dto.MaskingRuleAddDto;
import com.example.entity.dto.MaskingRuleEditDto;
import com.example.entity.vo.MaskingRuleVo;
import com.example.entity.vo.algorithmconfig.AlgorithmConfig;
import com.example.entity.vo.algorithmconfig.CoverAlgorithmConfig;
import com.example.entity.vo.algorithmconfig.EncryptAlgorithmConfig;
import com.example.entity.vo.algorithmconfig.HashAlgorithmConfig;
import com.example.service.IMaskingRuleService;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;


import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;


@Service
public class MaskingRuleServiceImpl implements IMaskingRuleService {

    @Resource
    private MaskingRuleMapper maskingRuleMapper;

    @Resource
    private SensitiveTypeDao sensitiveTypeDao;

    @Override
    public Page<MaskingRuleVo> selectPage(BaseDTO pageDto) {

        Page<MaskingRule> page = new Page<>(pageDto.getPageNum(), pageDto.getPageSize());
        LambdaQueryWrapper<MaskingRule> wrapper = Wrappers.lambdaQuery();
        if (StringUtils.isNotBlank(pageDto.getName())) {
            wrapper.like(MaskingRule::getName, pageDto.getName());
        }
        if (StringUtils.isNotEmpty(pageDto.getType())) {
            wrapper.eq(MaskingRule::getType, pageDto.getType());
        }

        Page<MaskingRule> maskingRulePage = maskingRuleMapper.selectPage(page, wrapper);

        List<MaskingRuleVo> voList = page.getRecords().stream().map(rule -> {
            MaskingRuleVo vo = new MaskingRuleVo();
            BeanUtils.copyProperties(rule, vo);
            vo.setAlgorithmTypeName(Optional.ofNullable(rule.getAlgorithmType()).map(AlgorithmTypeEnum::getDesc).orElse(null));
            // 反序列化算法配置
            AlgorithmConfig config = algorithmConfigParser(rule.getAlgorithmConfig(), rule.getAlgorithmType());
            vo.setAlgorithmConfig(config);
            vo.setAlgorithmConfigDesc(config != null ? config.generateDesc() : null);

            // 敏感类型名称
            vo.setSensitiveTypeName(getSensitiveTypeName(rule.getSensitiveTypeId()));

            return vo;
        }).collect(Collectors.toList());

        Page<MaskingRuleVo> voPage = new Page<>();
        BeanUtils.copyProperties(maskingRulePage, voPage);
        voPage.setRecords(voList);
        return voPage;
    }

    @Override
    public Boolean add(MaskingRuleAddDto addDto) {
        AlgorithmConfig algorithmConfig = null;

        // 根据 algorithmType 手动决定使用哪个子类进行反序列化
        if (addDto.getAlgorithmType() == AlgorithmTypeEnum.COVER) {
            algorithmConfig = JSONObject.parseObject(
                    addDto.getConfigJson().toJSONString(),
                    CoverAlgorithmConfig.class
            );
        } else if (addDto.getAlgorithmType() == AlgorithmTypeEnum.HASH) {
            algorithmConfig = JSONObject.parseObject(
                    addDto.getConfigJson().toJSONString(),
                    HashAlgorithmConfig.class
            );
        } else if (addDto.getAlgorithmType() == AlgorithmTypeEnum.ENCRYPT) {
            algorithmConfig = JSONObject.parseObject(
                    addDto.getConfigJson().toJSONString(),
                    EncryptAlgorithmConfig.class
            );
        }

        // 设置算法类型（供多态反序列化使用）
        algorithmConfig.setAlgorithmType(addDto.getAlgorithmType());


        String username = CurrentUserUtil.getCurrentUsername();

        // 继续后续操作
        MaskingRule rule = new MaskingRule();
        rule.setSensitiveTypeId(addDto.getSensitiveTypeId());
        rule.setName(addDto.getName());
        rule.setType("自定义");
        rule.setAlgorithmType(addDto.getAlgorithmType());
        // 转为JSON字符串存储
        rule.setAlgorithmConfig(JSONObject.toJSONString(algorithmConfig));
        rule.setCreatedBy(username);
        rule.setUpdatedBy(username);
        rule.setCreatedTime(LocalDateTime.now());
        rule.setUpdatedTime(LocalDateTime.now());

        return maskingRuleMapper.insert(rule) > 0;
    }


    @Override
    public Boolean edit(MaskingRuleEditDto editDto) {
        MaskingRule maskingRule = maskingRuleMapper.selectById(editDto.getId());
        if (maskingRule != null) {
            AlgorithmConfig algorithmConfig = null;

            // 根据 algorithmType 手动决定使用哪个子类进行反序列化
            if (editDto.getAlgorithmType() == AlgorithmTypeEnum.COVER) {
                algorithmConfig = JSONObject.parseObject(
                        editDto.getConfigJson().toJSONString(),
                        CoverAlgorithmConfig.class
                );
            } else if (editDto.getAlgorithmType() == AlgorithmTypeEnum.HASH) {
                algorithmConfig = JSONObject.parseObject(
                        editDto.getConfigJson().toJSONString(),
                        HashAlgorithmConfig.class
                );
            } else if (editDto.getAlgorithmType() == AlgorithmTypeEnum.ENCRYPT) {
                algorithmConfig = JSONObject.parseObject(
                        editDto.getConfigJson().toJSONString(),
                        EncryptAlgorithmConfig.class
                );
            }
            maskingRule.setName(editDto.getName());
            maskingRule.setUpdatedBy(CurrentUserUtil.getCurrentUsername());
            maskingRule.setUpdatedTime(LocalDateTime.now());
            maskingRule.setAlgorithmConfig(JSONObject.toJSONString(algorithmConfig));
            maskingRule.setAlgorithmType(editDto.getAlgorithmType());
            maskingRule.setSensitiveTypeId(editDto.getSensitiveTypeId());
            return maskingRuleMapper.updateById(maskingRule) > 0;
        }
        return false;
    }

    @Override
    public Boolean delete(Integer id) {
        return maskingRuleMapper.deleteById(id) > 0;
    }

    private String getSensitiveTypeName(Long sensitiveTypeId) {
        return sensitiveTypeDao.getSentiveTypeName(sensitiveTypeId);
    }

    public AlgorithmConfig algorithmConfigParser(String json, AlgorithmTypeEnum type) {
        if (type == null || StringUtils.isBlank(json)) {
            return null;
        }

        switch (type) {
            case COVER:
                return JSONObject.parseObject(json, CoverAlgorithmConfig.class);
            case HASH:
                return JSONObject.parseObject(json, HashAlgorithmConfig.class);
            case ENCRYPT:
                return JSONObject.parseObject(json, EncryptAlgorithmConfig.class);
            default:
                return null;
        }
    }
}
